TimesheetApp   A
last analyzed

Complexity

Total Complexity 34

Size/Duplication

Total Lines 217
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 123
dl 0
loc 217
rs 9.68
c 0
b 0
f 0
wmc 34

9 Functions

Rating   Name   Duplication   Size   Complexity  
A update_timespan 0 18 3
A getWindowTitle 0 9 2
A filter2_change 0 16 4
C push 0 42 10
A add_action_handler 0 16 2
A filter_change 0 18 3
A pm_id_changed 0 20 3
A et2_ready 0 18 2
B add_with_extras 0 35 5
1
/**
2
 * EGroupware - Timesheet - Javascript UI
3
 *
4
 * @link http://www.egroupware.org
5
 * @package timesheet
6
 * @author Hadi Nategh	<hn-AT-stylite.de>
7
 * @copyright (c) 2008-16 by Ralf Becker <RalfBecker-AT-outdoor-training.de>
8
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
9
 */
10
11
/*egw:uses
12
	/api/js/jsapi/egw_app.js
13
 */
14
15
import 'jquery';
16
import 'jqueryui';
17
import '../jsapi/egw_global';
18
import '../etemplate/et2_types';
19
20
import { EgwApp } from '../../api/js/jsapi/egw_app';
21
22
/**
23
 * UI for timesheet
24
 *
25
 * @augments AppJS
26
 */
27
class TimesheetApp extends EgwApp
28
{
29
	readonly appname = 'timesheet';
30
31
	/**
32
	 * This function is called when the etemplate2 object is loaded
33
	 * and ready.  If you must store a reference to the et2 object,
34
	 * make sure to clean it up in destroy().
35
	 *
36
	 * @param et2 etemplate2 Newly ready object
37
	 * @param string name
38
	 */
39
	et2_ready(et2, name : string)
40
	{
41
		// call parent
42
		super.et2_ready(et2, name);
43
44
		if (typeof et2.templates['timesheet.index'] != "undefined")
45
		{
46
			this.filter_change();
47
			this.filter2_change();
48
		}
49
	}
50
51
	/**
52
	 *
53
	 */
54
	filter_change()
55
	{
56
		var filter = this.et2.getWidgetById('filter');
57
		var dates = this.et2.getWidgetById('timesheet.index.dates');
58
59
		if (filter && dates)
60
		{
61
			dates.set_disabled(filter.get_value() !== "custom");
62
			if (filter.value == "custom")
63
			{
64
				jQuery(this.et2.getWidgetById('startdate').getDOMNode()).find('input').focus();
65
			}
66
		}
67
		return true;
68
	}
69
70
	/**
71
	 * show or hide the details of rows by selecting the filter2 option
72
	 * either 'all' for details or 'no_description' for no details
73
	 *
74
	 */
75
	filter2_change()
76
	{
77
		var nm = this.et2.getWidgetById('nm');
78
		var filter2 = this.et2.getWidgetById('filter2');
79
80
		if (nm && filter2)
81
		{
82
			egw.css("#timesheet-index span.timesheet_titleDetails","font-weight:" + (filter2.getValue() == '1' ? "bold;" : "normal;"));
83
			// Show / hide descriptions
84
			egw.css(".et2_label.ts_description","display:" + (filter2.getValue() == '1' ? "block;" : "none;"));
85
		}
86
	}
87
88
	/**
89
	 * Wrapper so add action in the context menu can pass current
90
	 * filter values into new edit dialog
91
	 *
92
	 * @see add_with_extras
93
	 *
94
	 * @param {egwAction} action
95
	 * @param {egwActionObject[]} selected
96
	 */
97
	add_action_handler(action, selected)
98
	{
99
		var nm = action.getManager().data.nextmatch || false;
100
		if(nm)
101
		{
102
			this.add_with_extras(nm);
103
		}
104
	}
105
106
	/**
107
	 * Opens a new edit dialog with some extra url parameters pulled from
108
	 * nextmatch filters.
109
	 *
110
	 * @param {et2_widget} widget Originating/calling widget
111
	 */
112
	add_with_extras(widget)
113
	{
114
		var nm = widget.getRoot().getWidgetById('nm');
115
		var nm_value = nm.getValue() || {};
116
117
		var extras : any = {};
118
		if (nm_value.cat_id)
119
		{
120
			extras.cat_id = nm_value.cat_id;
121
		}
122
123
		if (nm_value.col_filter && nm_value.col_filter.linked)
124
		{
125
			var split = nm_value.col_filter.linked.split(':') || '';
126
			extras.link_app = split[0] || '';
127
			extras.link_id = split[1] || '';
128
		}
129
		if (nm_value.col_filter && nm_value.col_filter.pm_id)
130
		{
131
			extras.link_app = 'projectmanager';
132
			extras.link_id = nm_value.col_filter.pm_id;
133
		}
134
		else if (nm_value.col_filter && nm_value.col_filter.ts_project)
135
		{
136
			extras.ts_project = nm_value.col_filter.ts_project;
137
		}
138
139
		egw.open('','timesheet','add',extras);
140
	}
141
142
	/**
143
	 * Change handler for project selection to set empty ts_project string, if project get deleted
144
	 *
145
	 * @param {type} _egw
146
	 * @param {et2_widget_link_entry} _widget
147
	 * @returns {undefined}
148
	 */
149
	pm_id_changed(_egw, _widget)
150
	{
151
		// Update price list
152
		var ts_pricelist = _widget.getRoot().getWidgetById('pl_id');
153
		egw.json('projectmanager_widget::ajax_get_pricelist',[_widget.getValue()],function(value) {
154
			ts_pricelist.set_select_options(value||{})
155
		}).sendRequest(true);
156
157
		var ts_project = this.et2.getWidgetById('ts_project');
158
		if (ts_project)
159
		{
160
			ts_project.set_blur(_widget.getValue() ? _widget.search.val() : '');
161
		}
162
	}
163
164
	/**
165
	 * Update custom filter timespan, without triggering a change
166
	 */
167
	update_timespan(start, end)
168
	{
169
		if(this && this.et2)
170
		{
171
			var nm = this.et2.getWidgetById('nm');
172
			if(nm)
173
			{
174
				// Toggle update_in_progress to avoid another request
175
				nm.update_in_progress = true;
176
				this.et2.getWidgetById('startdate').set_value(start);
177
				this.et2.getWidgetById('enddate').set_value(end);
178
				nm.activeFilters.startdate = start;
179
				nm.activeFilters.enddate = end;
180
				nm.update_in_progress = false;
181
			}
182
		}
183
	}
184
185
	/**
186
	 * Get title in order to set it as document title
187
	 * @returns {string}
188
	 */
189
	getWindowTitle()
190
	{
191
		var widget = this.et2.getWidgetById('ts_title');
192
		if(widget) return widget.options.value;
193
	}
194
195
	private _grants : any;
196
197
	/**
198
	 * Handle a push notification about entry changes from the websocket
199
	 *
200
	 * @param  pushData
201
	 * @param {string} pushData.app application name
202
	 * @param {(string|number)} pushData.id id of entry to refresh or null
203
	 * @param {string} pushData.type either 'update', 'edit', 'delete', 'add' or null
204
	 * - update: request just modified data from given rows.  Sorting is not considered,
205
	 *		so if the sort field is changed, the row will not be moved.
206
	 * - edit: rows changed, but sorting may be affected.  Requires full reload.
207
	 * - delete: just delete the given rows clientside (no server interaction neccessary)
208
	 * - add: requires full reload for proper sorting
209
	 * @param {object|null} pushData.acl Extra data for determining relevance.  eg: owner or responsible to decide if update is necessary
210
	 * @param {number} pushData.account_id User that caused the notification
211
	 */
212
	push(pushData)
213
	{
214
		// timesheed does NOT care about other apps data
215
		if (pushData.app !== this.appname) return;
216
217
		if (pushData.type === 'delete')
218
		{
219
			return super.push(pushData);
220
		}
221
222
		// all other cases (add, edit, update) are handled identical
223
		// check visibility
224
		if (typeof this._grants === 'undefined')
225
		{
226
			this._grants = egw.grants(this.appname);
227
		}
228
		if (typeof this._grants[pushData.acl] === 'undefined') return;
229
230
		// check if we might not see it because of an owner filter
231
		let nm = this.et2?.getWidgetById('nm');
232
		let nm_value = nm?.getValue();
233
		if (nm && nm_value && typeof nm_value.col_filter?.ts_owner !== 'undefined')
234
		{
235
			if (!nm_value.col_filter.ts_owner || nm_value.col_filter.ts_owner == pushData.acl)
236
			{
237
				this.updateList(nm, pushData);
238
			}
239
		}
240
	}
241
}
242
243
app.classes.timesheet = TimesheetApp;
244